<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双冒号运算符</title>
</head>
<body>
    <h1>双冒号运算符</h1>
    <h2>用于函数绑定</h2>

    <script>
        // 目前的写法
        const logger = {
            messages: [],
            log(message) {
                this.messages.push(message);
                console.log(message);
            }
        };

        // 使用bind
        const boundLog = logger.log.bind(logger);
        boundLog('Hello');

        // 双冒号运算符提案的写法
        /*
        const boundLog = logger::logger.log;
        boundLog('Hello');

        // 如果是同一个对象，可以省略第一个参数
        const log = ::logger.log;
        log('Hello');
        */

        // 实际应用示例
        // 1. 模拟双冒号运算符
        function bind(fn, context) {
            return function(...args) {
                return fn.apply(context, args);
            };
        }

        class EventEmitter {
            constructor() {
                this.events = {};
            }

            on(event, listener) {
                if (!this.events[event]) {
                    this.events[event] = [];
                }
                this.events[event].push(bind(listener, this));
            }

            emit(event, ...args) {
                const listeners = this.events[event];
                if (listeners) {
                    listeners.forEach(listener => listener(...args));
                }
            }
        }

        // 2. 方法链式调用
        class Calculator {
            constructor(value = 0) {
                this.value = value;
            }

            add(n) {
                this.value += n;
                return this;
            }

            multiply(n) {
                this.value *= n;
                return this;
            }

            toString() {
                return String(this.value);
            }
        }

        const calc = new Calculator();
        const boundAdd = bind(calc.add, calc);
        const boundMultiply = bind(calc.multiply, calc);

        boundAdd(5);
        boundMultiply(2);
        console.log(calc.toString()); // "10"
    </script>
</body>
</html> 